package com.niiwoo.civet.account.service.local;

import com.niiwoo.civet.account.dao.entity.AccountBase;
import com.niiwoo.civet.account.dao.entity.OpenAccountRecord;
import com.niiwoo.civet.account.dao.mapper.AccountBaseMapperExt;
import com.niiwoo.civet.account.dao.mapper.AccountPersonMapper;
import com.niiwoo.civet.account.dao.mapper.ActivateAccountOrderMapper;
import com.niiwoo.civet.account.dao.mapper.BankCardMapperExt;
import com.niiwoo.civet.account.dao.mapper.GroupAccountCorrelateOrderMapperExt;
import com.niiwoo.civet.account.dao.mapper.OpenAccountOrderMapperExt;
import com.niiwoo.civet.account.dao.mapper.OpenAccountRecordMapperExt;
import com.niiwoo.civet.account.dto.Tuple2;
import com.niiwoo.tripod.lanmao.enums.UserRoleEnum;
import java.util.List;
import java.util.function.Supplier;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;

/**
 * 开户记录服务
 */
@Service
public class OpenAccountRecordService {

    @Autowired
    OpenAccountRecordMapperExt openAccountRecordMapper;

    @Autowired
    OpenAccountOrderMapperExt openAccountOrderMapper;

    @Autowired
    AccountBaseMapperExt accountBaseMapperExt;

    @Autowired
    AccountService accountService;

    @Autowired
    AccountPersonMapper accountPersonMapper;

    @Autowired
    BankCardMapperExt bankCardMapperExt;

    @Autowired
    GroupAccountCorrelateOrderMapperExt groupAccountCorrelateOrderMapper;

    @Autowired
    ActivateAccountOrderMapper activateAccountOrderMapper;

    /**
     * 始化账号
     *
     * @param accountBase 基础账户信息
     // * @param accountPerson 个人账户信息
     // * @param bankCardOpt 开户银行卡， 只会在第一次开户成功或激活时写入银行卡记录
     */
    private boolean saveAccountInfo(boolean isInit, AccountBase accountBase, Supplier<Boolean> s1, Supplier<Boolean> s2) {
        return (isInit ? accountBaseMapperExt.insertSelective(accountBase) > 0 : accountBaseMapperExt.updateByPrimaryKeySelective(accountBase) > 0) && s1.get() && s2.get();
    }

    /**
     * 获取开户记录列表
     *
     * @param userId 用户id
     */
    public List<OpenAccountRecord> getByUserId(String userId) {
        return openAccountRecordMapper.selectByUserId(userId);
    }

    /**
     * 获取开户记录
     *
     * @param userId 用户id
     * @param roleEnum 角色
     */
    public OpenAccountRecord getByUserIdAndRole(String userId, UserRoleEnum roleEnum) {
        return openAccountRecordMapper.selectByUserIdAndRole(userId, Integer.valueOf(roleEnum.getValue()).byteValue());
    }

    /**
     * 保存或更新记录
     *
     * @param present 开户记录是否存在
     * @param record 开户记录
     */
    @Transactional(isolation = Isolation.READ_COMMITTED)
    public boolean saveRecord(boolean present, OpenAccountRecord record) {
        return present ? openAccountRecordMapper.updateStatusById(record) > 0 : openAccountRecordMapper.insertSelective(record) > 0;
    }

    /**
     * 查询账户信息
     *
     * @param userId 用户ID
     * @param userRole 账户角色
     */
    public AccountBase getAccountBase(String userId, UserRoleEnum userRole) {
        return accountService.getNiiwooAccount(userId, userRole);
    }

    @Transactional(isolation = Isolation.READ_COMMITTED)
    public boolean saveRecordAndAccountOrder(boolean isRecordPresent, OpenAccountRecord record, Supplier<Boolean> s) {
        return saveRecord(isRecordPresent, record) && (s == null || s.get());
    }

    @Transactional(isolation = Isolation.READ_COMMITTED)
    public Tuple2<Boolean, Boolean> saveRecordAndAccountOrderAndAccountInfo(OpenAccountRecord record, Supplier<Boolean> s1, boolean isInitAccount, AccountBase updateBase, Supplier<Boolean> s2, Supplier<Boolean> s3) {
        OpenAccountRecord srcRecord = openAccountRecordMapper.selectByPrimaryKeyForUpdate(record.getId());
        if (srcRecord.getStatus().equals(record.getStatus())) {
            return new Tuple2<>(true, false);
        }
        boolean success = saveRecordAndAccountOrder(true, record, s1) && saveAccountInfo(isInitAccount, updateBase, s2, s3);
        return new Tuple2<>(success, success);
    }

    @Transactional(isolation = Isolation.READ_COMMITTED)
    public Tuple2<Boolean, Boolean> saveRecordAndAccountOrderIfPossible(OpenAccountRecord record, Supplier<Boolean> s) {
        OpenAccountRecord srcRecord = openAccountRecordMapper.selectByPrimaryKeyForUpdate(record.getId());
        if (srcRecord.getStatus().equals(record.getStatus())) {
            return new Tuple2<>(true, false);
        }
        boolean success = saveRecordAndAccountOrder(true, record, s);
        return new Tuple2<>(success, success);
    }

    public List<AccountBase> getAccountBaseList(String userId) {
        return accountService.listAccountByUserId(userId);
    }

    public OpenAccountRecord getByAccountNo(String accountNo) {
        return openAccountRecordMapper.selectByAccountNo(accountNo);
    }
}
